package com.egreen.order.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.egreen.common.States;
import com.egreen.common.pojo.DTO.order.AcceptOrderDTO;
import com.egreen.common.pojo.DTO.asset.OperatePointRecordingDTO;
import com.egreen.common.pojo.entity.order.*;
import com.egreen.common.pojo.entity.user.LocationDetail;
import com.egreen.common.pojo.entity.user.User;
import com.egreen.common.pojo.entity.user.UserLocation;
import com.egreen.common.pojo.entity.user.UserLoginAccount;
import com.egreen.common.serviceapi.asset.IAssetServiceApi;
import com.egreen.common.serviceapi.user.IUserServiceApi;
import com.egreen.order.ex.exceptions.OrderException;
import com.egreen.order.dao.*;
import com.egreen.common.pojo.DTO.order.CommitOrderDTO;
import com.egreen.common.pojo.VO.order.AgentOrderVO;
import com.egreen.common.pojo.VO.order.GetallOrderVO;
import com.egreen.order.service.IOrderService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.sql.SQLClientInfoException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author cloudJiang
 * @since 2022-07-16
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderDao, Order> implements IOrderService {
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private OrderDetailDao orderDetailDao;
    @Autowired
    private OrderStatesDao orderStatesDao;
    @Autowired
    private RecyclableNameDao recyclableNameDao;
    @Autowired
    private RecyclableTypeDao recyclableTypeDao;
    @DubboReference
    IUserServiceApi userServiceApi;
    @DubboReference
    IAssetServiceApi assetServiceApi;


    //todo 修改订单提交逻辑，在订单提交时将位置信息记录在OrderLocation中
    @Override
    @Transactional(rollbackFor = {SQLClientInfoException.class, OrderException.class})
    public void commitOrder(CommitOrderDTO commitOrderDTO) {
        /**
         * 提交订单，根据传递进来的卖家id,物品名称，物品种类，生成相应的订单状态表和订单详情表
         * 设置订单状态为0，根据物品种类和物品重量计算出总价格，根据状态表id和详情表id生成新的order表
         */
        Long salId = commitOrderDTO.getSalId();
        String name = commitOrderDTO.getName();
        String type = commitOrderDTO.getType();
        BigDecimal weight = commitOrderDTO.getWeight();
        if (salId == null || name.isEmpty() || type.isEmpty() || weight == null) {
            throw new OrderException(States.ERR_BAD_REQUEST.getStates(), "参数不能为null");
        }
        Map<String, Object> map = new HashMap<>();
        map.put("name", name);
        List<RecyclableName> recyclable = recyclableNameDao.selectByMap(map);
        if (recyclable == null) {
            throw new OrderException(States.ERR_SELECT.getStates(), "查询数据失败，请检查参数id");
        }
        RecyclableName recyclables = recyclable.get(0);
        Integer nameId = recyclables.getId();
        Integer typeId = recyclables.getTypeId();
        BigDecimal price = recyclables.getPrice();
        //计算出总价格
        BigDecimal totalPrice = price.multiply(weight);
        OrderDetail orderDetail = new OrderDetail();
        orderDetail.setRecNameId(nameId);
        orderDetail.setRecTypeId(typeId);
        orderDetail.setWeight(weight);
        if (commitOrderDTO.getDonated() == 1) {
            BigDecimal free = new BigDecimal(0);
            orderDetail.setTotalPrice(free);
        } else {
            orderDetail.setTotalPrice(totalPrice);
        }
        int insert = orderDetailDao.insert(orderDetail);
        if (insert != 1) {
            throw new OrderException(States.ERR_SELECT.getStates(), "插入数据失败，请稍后再试");
        }
        //生成新的orderStates表
        OrderStates orderStates = new OrderStates();
        orderStates.setStates(0);
        orderStates.setStartTime(LocalDateTime.now());
        int insert1 = orderStatesDao.insert(orderStates);
        if (insert1 != 1) {
            throw new OrderException(States.ERR_SELECT.getStates(), "插入数据失败，请稍后再试");
        }
        Long statesId = orderStates.getId();
        Long detailId = orderDetail.getId();
        //生成新的order表
        Order order = new Order();
        order.setSalId(salId);
        order.setStatesId(statesId);
        order.setDetailId(detailId);
        order.setDonated(commitOrderDTO.getDonated());
        int insert2 = orderDao.insert(order);
        if (insert2 != 1) {
            throw new OrderException(States.ERR_SELECT.getStates(), "插入数据失败，请稍后再试");
        }
    }

    // TODO 获取订单逻辑修改，根据OrderLocation查找订单
    @Override
    public List<AgentOrderVO> getNearbyOrder(Integer userState, Long locationId) {
        //生成包含订单信息的集合
        if (userState == 0 || locationId == null) {
            throw new OrderException(States.ERR_BAD_REQUEST.getStates(), "参数不能为Null");
        }
        List<AgentOrderVO> returnList = new ArrayList<>();
        List<User> nearbyUsers = new ArrayList<>();
        //根据传进来的locationId进行查询获取用户的具体详细位置
        UserLocation userLocation =
                userServiceApi.selectLocationById(locationId);
        LocationDetail locationDetail =
                userServiceApi.selectLocationDetailById(userLocation.getDetailId());
        if (userLocation == null || locationDetail == null) {
            throw new OrderException(States.ERR_SELECT.getStates(), "查询数据失败，请检查当前参数id");
        }
        //进行代理等级的判断，代理等级越高查询的订单范围越大
        if (userState == 3) {  //当前用户是城市代理
            nearbyUsers = userServiceApi.getUsersFromCity(userLocation.getProvinceId(), userLocation.getCityName());
        } else if (userState == 2) {
            nearbyUsers = userServiceApi.getUsersFromDetail(userLocation.getProvinceId(),
                    userLocation.getCityName(), locationDetail.getDistrict(), "");
        } else if (userState == 1) {
            nearbyUsers = userServiceApi.getUsersFromDetail(userLocation.getProvinceId(),
                    userLocation.getCityName(), locationDetail.getDistrict(), locationDetail.getCommunity());
        }
        //遍历用户
        for (User user : nearbyUsers) {
            Long userId = user.getId();
            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("sal_id", userId);
            wrapper.eq("deleted", 0);
            List<Order> userOrders = orderDao.selectList(wrapper);
            for (Order order : userOrders) {
                Long statesId = order.getStatesId();
                QueryWrapper queryWrapper = new QueryWrapper();
                queryWrapper.eq("id", statesId);
                queryWrapper.eq("states", 0);
                List<OrderStates> list = orderStatesDao.selectList(queryWrapper);
                for (OrderStates orderStates : list) {
                    Long StatesId = orderStates.getId();
                    QueryWrapper queryWrapper1 = new QueryWrapper();
                    queryWrapper1.eq("states_Id", StatesId);
                    queryWrapper1.eq("sal_id", userId);
                    queryWrapper1.eq("deleted", 0);
                    List<Order> list1 = orderDao.selectList(queryWrapper1);
                    //查询用户的位置信息
                    UserLocation location = userServiceApi.selectLocationById(user.getLocationId());
                    LocationDetail locationDetail1 = userServiceApi.selectLocationDetailById(location.getDetailId());
                    //开始遍历订单
                    for (Order order2 : list1) {
                        AgentOrderVO agentOrderVO = new AgentOrderVO();
                        UserLoginAccount userLoginAccount = userServiceApi.selectLoginById(user.getLoginAccountId());
                        agentOrderVO.setPhone(userLoginAccount.getPhone());
                        //查询订单的相关信息
                        OrderDetail orderDetail = orderDetailDao.selectById(order2.getDetailId());
                        OrderStates orderStates1 = orderStatesDao.selectById(order2.getStatesId());
                        if (orderDetail == null || orderStates1 == null) {
                            throw new OrderException(States.ERR_SELECT.getStates(), "查询数据失败，请检查参数id");
                        }
                        agentOrderVO.setDonated(order2.getDonated());
                        agentOrderVO.setOrderId(order2.getId());
                        agentOrderVO.setPrice(orderDetail.getTotalPrice());
                        agentOrderVO.setDistrict(userLocation.getCityName() + locationDetail1.getDistrict() +
                                locationDetail1.getCommunity());
                        agentOrderVO.setWeight(orderDetail.getWeight());
                        agentOrderVO.setState(orderStates1.getStates());
                        agentOrderVO.setUserName(user.getUserName());
                        String recyclableName = (recyclableNameDao.selectById(orderDetail.getRecNameId())).getName();
                        String recyclableType = (recyclableTypeDao.selectById(orderDetail.getRecTypeId())).getTypeName();
                        agentOrderVO.setRecyclableName(recyclableName);
                        agentOrderVO.setRecyclableType(recyclableType);
                        returnList.add(agentOrderVO);
                    }
                }
            }
        }
        return returnList;
    }

    @Override
    public List<GetallOrderVO> getAllOrder(Long userId, Integer states) {
        /**
         * 获取历史订单
         * 根据传递进来userId和states进行查询查找符合的条件订单
         */
        if (userId == null || states == null) {
            throw new OrderException(States.ERR_BAD_REQUEST.getStates(), "参数不能为null");
        }
        List<GetallOrderVO> orderVOList = new ArrayList<>();
        //根据用户id查找与之相符合的订单
        QueryWrapper<Order> wrapper = new QueryWrapper();
        wrapper.eq("sal_id", userId).or().eq("buy_id", userId);
        wrapper.eq("deleted", 0);
        List<Order> orders = orderDao.selectList(wrapper);
        for (Order order : orders) {
            Long statesId = order.getStatesId();
            QueryWrapper<OrderStates> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("id", statesId);
            queryWrapper.eq("states", states);
            //查找符合id和符合states的订单
            List<OrderStates> orderStates = orderStatesDao.selectList(queryWrapper);
            for (OrderStates orderStates1 : orderStates) {
                int state = orderStates1.getStates();
                Long statesIds = orderStates1.getId();
                QueryWrapper<Order> orderQueryWrapper = new QueryWrapper<>();
                orderQueryWrapper.eq("states_Id", statesIds);
                List<Order> orderdetail = orderDao.selectList(orderQueryWrapper);
                for (Order order1 : orderdetail) {
                    GetallOrderVO userOrderVO = new GetallOrderVO();
                    //判断要查询的是卖方id还是买房id
                    if (userId.equals(order1.getSalId())) {
                        User user = userServiceApi.selectUserById(userId);
                        String username = user.getUserName();
                        userOrderVO.setUserName(username);
                    } else if (userId.equals(order1.getBuyId())) {
                        User user = userServiceApi.selectUserById(userId);
                        String username = user.getUserName();
                        userOrderVO.setUserName(username);
                    }
                    userOrderVO.setDonated(order1.getDonated());
                    userOrderVO.setState(state);
                    userOrderVO.setId(order1.getId());
                    //查出statrttime和endtime并赋值给vo
                    Long statesId1 = order1.getStatesId();
                    OrderStates orderStates2 = orderStatesDao.selectById(statesId1);
                    userOrderVO.setStartTime(orderStates2.getStartTime());
                    userOrderVO.setEndTime(orderStates2.getEndTime());
                    //取出weight和totalPrice赋值给vo
                    Long detailId = order1.getDetailId();
                    OrderDetail orderDetail = orderDetailDao.selectById(detailId);
                    userOrderVO.setWeight(orderDetail.getWeight());
                    userOrderVO.setTotalPrice(orderDetail.getTotalPrice());
                    //取出商品名称和商品种类id并赋值给vo
                    int recNameId = orderDetail.getRecNameId();
                    int recTypeId = orderDetail.getRecTypeId();
                    RecyclableName recyclableName = recyclableNameDao.selectById(recNameId);
                    RecyclableType recyclableType = recyclableTypeDao.selectById(recTypeId);
                    String name = recyclableName.getName();
                    String type = recyclableType.getTypeName();
                    BigDecimal price = recyclableName.getPrice();
                    userOrderVO.setRecyclableName(name);
                    userOrderVO.setRecyclableType(type);
                    userOrderVO.setPrice(price);
                    orderVOList.add(userOrderVO);
                }
                if (orderVOList.isEmpty()) {
                    throw new OrderException(States.ERR_SELECT.getStates(), "查询数据失败，请检查参数id");
                }
            }
        }
        return orderVOList;
    }

    @Override
    public void commitErrorOrder(Long id, String errorMessage) {
        /**
         * 提交错误订单，根据订单id和错误原因,提交订单，订单状态修改为4
         */
        //获取传输进来的订单号
        if (errorMessage.isEmpty() || id == null) {
            throw new OrderException(States.ERR_BAD_REQUEST.getStates(), "参数不能为null");
        }
        Order order = orderDao.selectById(id);
        //如果获取的查询数据为空，返回1
        if (order == null) {
            throw new OrderException(States.ERR_SELECT.getStates(), "查询数据失败，请检查参数id");
        }
        //获取statesId,更改状态为4
        Long statesId = order.getStatesId();
        UpdateWrapper<OrderStates> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", statesId);
        OrderStates orderStates = new OrderStates();
        orderStates.setStates(4);
        orderStates.setErrorMessage(errorMessage);
        int update = orderStatesDao.update(orderStates, updateWrapper);
        if (update != 1) {
            throw new OrderException(States.ERR_UPDATE.getStates(), "更新数据失败，请稍后再试");
        }
    }

    @Override
    public void overOrder(Long id, BigDecimal weight) {
        /**
         * 完成订单
         * 根据传进来的id,改变状态为2，计算出总价格
         */
        if (id == null || weight == null) {
            throw new OrderException(States.ERR_BAD_REQUEST.getStates(), "参数不能为空");
        }
        //根据id查询得到statesId,detailId
        Order order = orderDao.selectById(id);
        if (order == null) {
            throw new OrderException(States.ERR_SELECT.getStates(), "查询数据失败，请检查参数id");
        }
        Long statesId = order.getStatesId();
        Long detailId = order.getDetailId();
        //通过statesid改变状态为2
        UpdateWrapper<OrderStates> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", statesId);
        OrderStates orderStates = new OrderStates();
        orderStates.setStates(2);
        int update = orderStatesDao.update(orderStates, updateWrapper);
        if (update != 1) {
            throw new OrderException(States.ERR_UPDATE.getStates(), "更新数据失败，请稍后再试");
        }
        //通过detailid查询到recNameId
        OrderDetail orderDetail = orderDetailDao.selectById(detailId);
        if (orderDetail == null) {
            throw new OrderException(States.ERR_SELECT.getStates(), "查询数据失败，请检查参数id");
        }
        Integer recNameId = orderDetail.getRecNameId();
        //通过recNameId查询到商品price
        RecyclableName recyclableName = recyclableNameDao.selectById(recNameId);
        if (recyclableName == null) {
            throw new OrderException(States.ERR_SELECT.getStates(), "查询数据失败，请检查参数id");
        }
        BigDecimal price = recyclableName.getPrice();
        //weight*price获取总价格totalPrice
        BigDecimal totalPrice = weight.multiply(price);
        //更改totalPrice
        UpdateWrapper<OrderDetail> updatePrice = new UpdateWrapper<>();
        updatePrice.eq("id", detailId);
        OrderDetail orderDetail1 = new OrderDetail();
        orderDetail1.setWeight(weight);
        if (order.getDonated() == 1) {
            BigDecimal free = new BigDecimal(0);
            orderDetail1.setTotalPrice(free);
        } else {
            orderDetail1.setTotalPrice(totalPrice);
        }
        int updateweightandtPrice = orderDetailDao.update(orderDetail1, updatePrice);
        if (updateweightandtPrice != 1) {
            throw new OrderException(States.ERR_UPDATE.getStates(), "更新数据失败，请稍后再试");
        }
    }

    @Override
    public void endOrder(Long id) {
        /**
         * 结束订单
         * 根据传递进来的订单id，只有当订单状态为2时修改为3，同时更新订单结束时间，结束后为双方发送积分
         * 订单状态
         * 等待接单 0
         * 已接单 1
         * 订单已完成处理 2
         * 结束 3
         * 订单异常 4
         * 若用户提交订单异常则需填入异常消息。
         */
        if (id == null) {
            throw new OrderException(States.ERR_BAD_REQUEST.getStates(), "参数不能为空");
        }
        Order order = orderDao.selectById(id);
        if (order == null) {
            throw new OrderException(States.ERR_SELECT.getStates(), "查询数据失败，请检查参数id");
        }
        Integer donated = order.getDonated();
        Long statesId = order.getStatesId();
        UpdateWrapper<OrderStates> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", statesId);
        updateWrapper.eq("states", 2);
        OrderStates orderStates = new OrderStates();
        orderStates.setStates(3);
        LocalDateTime now = LocalDateTime.now();
        orderStates.setEndTime(now);
        int rows = orderStatesDao.update(orderStates, updateWrapper);
        if (rows != 1) {
            throw new OrderException(States.ERR_UPDATE.getStates(), "更新数据失败，请稍后再试");
        }
        //  调用资产模块，订单结束时发送积分
        OrderDetail orderDetail = orderDetailDao.selectById(order.getDetailId());
        BigDecimal weight = orderDetail.getWeight();
        int addPointBalance = weight.intValue();
        //为买家发松积分
        User buyUser = userServiceApi.selectUserById(order.getBuyId());
        OperatePointRecordingDTO buyUserAddPoint = new OperatePointRecordingDTO();
        buyUserAddPoint.setId(order.getBuyId());
        buyUserAddPoint.setPointAccountId(buyUser.getPointAccountId());
        buyUserAddPoint.setOperate("增加");
        if (donated == 1) {
            //表示为捐赠订单
            buyUserAddPoint.setOperatePointNum(addPointBalance * 10);
        } else {
            buyUserAddPoint.setOperatePointNum(addPointBalance);
        }
        assetServiceApi.updateByPoint(buyUserAddPoint);
        //为卖家发送积分
        User salUser = userServiceApi.selectUserById(order.getSalId());
        OperatePointRecordingDTO salUserAddPoint = new OperatePointRecordingDTO();
        salUserAddPoint.setId(order.getSalId());
        salUserAddPoint.setPointAccountId(salUser.getPointAccountId());
        salUserAddPoint.setOperate("增加");
        if (donated == 1) {
            salUserAddPoint.setOperatePointNum(addPointBalance * 10);
        } else {
            salUserAddPoint.setOperatePointNum(addPointBalance);
        }
        assetServiceApi.updateByPoint(salUserAddPoint);
        //调用积分商城模块，发放积分
    }

    @Override
    public void handleErrorOrder(Long orderId) {

    }


    @Override
    public void acceptOrders(AcceptOrderDTO acceptOrderDTO) {
        Order order1 = orderDao.selectById(acceptOrderDTO.getId());
        OrderStates orderStates1 = orderStatesDao.selectById(order1.getStatesId());
        if (orderStates1.getStates() != 0) {
            throw new OrderException(States.ERR_UPDATE.getStates(), "该订单不是待接收订单！");
        }
        //接受订单
        Order order = new Order();
        order.setId(acceptOrderDTO.getId());
        order.setBuyId(acceptOrderDTO.getBuyId());
        int updateBuyId = orderDao.updateById(order);
        if (updateBuyId != 1) {
            throw new OrderException(States.ERR_UPDATE.getStates(), "更改状态失败");
        }
        Order acceptOrder = orderDao.selectById(acceptOrderDTO.getId());
        OrderStates orderStates = new OrderStates();
        orderStates.setId(acceptOrder.getStatesId());
        orderStates.setStates(1);
        int updateStates = orderStatesDao.updateById(orderStates);
        if (updateStates != 1) {
            throw new OrderException(States.ERR_UPDATE.getStates(), "更改状态失败");
        }
    }
}

